/**
 * 以比较松散的结构重新实现 精灵类 以期与原案保持一致。
 */
if(window) {
if(!window.Sprite) {
/* --======================================-- */
/* --======================================-- */
window.Sprite = (function () {

    /**
     * 精灵类构造函数
     * @param {String} name 精灵名字标识
     * @param {Painter} painter 三种绘制器之一
     * @param {Array(Behavior)} behaviors 行为类实例数组
     */
    var Sprite = function (name, painter) {
        if(name !== undefined) this.name = name;
        if(painter !== undefined) this.painter = painter;

        this.top = 0;
        this.left = 0;
        this.width = 10;
        this.height = 10;
        this.velocityX = 0;
        this.velocityY = 0;
        this.visible = true;
        this.animating = false;
        this.behaviors = [];
    }
    /* 精灵类原型对象 */
    Sprite.prototype = {
        paint: function (ctx) {
            if(this.painter !== undefined && this.visible) {
                this.painter.paint(this, ctx);
            }
        },
        update: function (ctx, time) {
            for(var i = 0; i < this.behaviors.length; i += 1) {
                this.behaviors[i].execute(this, ctx, time);
            }
        },

        /**
         * 新增行为，接收一个行为对象作为参数
         */
        addBehavior: function (execute, param) {
            if(!execute || typeof execute !== 'function') throw new Error('参数 execute 必要且为函数');
            if(typeof param === 'object' && param.length) throw new Error('参数 param 应为对象字面量');
            var behavior = new Behavior(execute, param);
            this.behaviors.push(behavior);
        },

        /**
         * 删除行为，接收一个行为对象作为参数
         */
        removeBehavior: function (behavior) {
            for(var i = 0; i < this.behaviors.length; i += 1) {
                if(behavior === this.behaviors[i]) {
                    this.behaviors.splice(i, 1);
                }
            }   
        }
    }


    /* --=================绘制器===============-- */
    /**
     * 描边填充绘制器
     * @param {Function} action 自定义绘制函数
     */
    Sprite.StrokeAndFillPainter = function (action) {
        if(typeof action !== 'function') throw new TypeError('参数 action 必要且为函数');
        this.action = action;
    }
    Sprite.StrokeAndFillPainter.prototype = {
        paint: function (sprite, ctx) {
            this.action(sprite, ctx);
        }
    }

    /**
     * 图像绘制器构造函数
     * @param {String} imgUrl 要绘制图像的链接
     */
    Sprite.ImagePainter = function (imgUrl) {
        this.image = new Image();
        this.image.src = imgUrl;
    }
    Sprite.ImagePainter.prototype = {
        paint: function (sprite, ctx) {
            var timer, that = this;
            if(that.image.complete) {
                ctx.drawImage(that.image, sprite.left, sprite.top, sprite.width, sprite.height);
            } else {
                timer = setInterval(function () {
                    if(that.image.complete) {
                        that.paint(sprite, ctx);
                        clearInterval(timer);
                    }
                }, 100);
            }
        }
    }

    /**
     * 精灵表绘制器构造函数
     * @param {Stirng} sheetUrl 精灵图url地址
     * @param {Array(Object)} cells 对象字面量数组，每个对象有x、y、w、h四个属性
     */
    Sprite.SpriteSheetPainter = function (sheetUrl, cells) {
        this.cells = cells || [];
        this.cellIndex = 0;
        this.sheet = new Image();
        this.sheet.src = sheetUrl;
    }
    Sprite.SpriteSheetPainter.prototype = {
        advance: function () {
            if(this.cellIndex === this.cells.length - 1) {
                this.cellIndex = 0;
            } else {
                this.cellIndex++;
            }
        },
        paint: function (sprite, ctx) {
            var timer, that = this;
            if(that.sheet.complete) {
                var cell = that.cells[that.cellIndex];
                ctx.drawImage(that.sheet, cell.x, cell.y, cell.w, cell.h, sprite.left, sprite.top, cell.w, cell.h);
            } else {
                timer = setInterval(function () {
                    if(that.sheet.complete) {
                        that.paint(sprite, ctx);
                        clearInterval(timer);
                    }
                }, 100);   
            }
        }
    }


    /* --=================行为类===============-- */
    /**
     * 行为类构造函数
     * @param {Function} execute 行为最终的执行函数
     * @param {Object} param 对象字面量，给出某个行为独有的辅助变量
     */
    var Behavior = function (execute, param) {
        if(!execute || typeof execute !== 'function') throw new Error('参数 execute 必要且为函数');
        this.action = execute;
        if(param && typeof param === 'object' && !param.length) {
            for(var key in param) {
                if(param.hasOwnProperty(key)) {
                    this[key] = param[key];
                }
            }
        }
    }
    Behavior.prototype = {
        execute: function (sprite, ctx, time) {
            this.action(sprite, this, ctx, time)
        }
    }

    
    /* --=================精灵绘制动画制作器===============-- */
    /**
     * 精灵动画制作构造函数，
     * 基于绘制器的动画制作器
     * @param {Array(Painter)} painters Painter数组
     * @param {Function} callback 回调
     */
    Sprite.SpriteAnimator = function (painters, callback) {
        this.painters = painters || [];
        this.callback = callback;
        this.duration = 1000;
        this.startTime = 0;
        this.index = 0;
    }
    Sprite.SpriteAnimator.prototype = {
        end: function (sprite, originalPainter) {
            sprite.animating = false;
            if(this.callback) callback(sprite);
            else sprite.painter = originalPainter;
        },
        start: function (sprite, duration) {
            var endTime = +new Date() + duration,
                period = duration / (this.painters.length),
                animator = this,
                originalPainter = sprite.painter,
                lastUpdate = 0,
                id;
            this.index = 0;
            sprite.animating = true;
            sprite.painter = this.painters[this.index];
            id = requestAnimationFrame( function spriteAnimatorAnimate(time) {
                if(time < endTime) {
                    if((time - lastUpdate) > period) {
                        sprite.painter = animator.painters[++animator.index];
                        lastUpdate = time;
                    }
                } else {
                    animator.end(sprite, originalPainter);
                    cancelAnimationFrame(id);
                }
            });
        }
    }


    return Sprite;
}());
/* --======================================-- */
/* --======================================-- */
} else {
    throw new Error('Sprite属性被占用');
}
} else {
    throw new Error('错误的环境');
}